home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / tex / wp2x110.zip / WP2X.C < prev    next >
C/C++ Source or Header  |  1991-08-18  |  53KB  |  1,516 lines

  1. /* $Id: wp2x.c 1.10 91/08/18 15:05:41 raymond Exp $ */
  2.  
  3. /* Before compiling, read the section titled `portability concerns'. */
  4.  
  5. /************************************************************************
  6.  * $Log:    wp2x.c $
  7.  * Revision 1.10  91/08/18  15:05:41  raymond
  8.  * Descriptor file stuff.
  9.  * 
  10.  * Revision 1.9  91/08/06  09:08:09  raymond
  11.  * add missing `break' in check_arity
  12.  * 
  13.  * Revision 1.8  91/08/06  08:31:21  raymond
  14.  * Avoid infinite loop if file is corrupted.
  15.  * Better error-checking on configuration file (new output scheme).
  16.  * 
  17.  * Revision 1.7  91/08/02  13:35:37  raymond
  18.  * Epsilonically better handling of environments that didn't end properly.
  19.  * Change return type of main() to keep gcc quiet.
  20.  * MSC support.
  21.  * 
  22.  * Revision 1.6  91/07/28  21:08:53  raymond
  23.  * BeginTabs et al, FNote#, ENote#, NegateTotal, more unsupported codes
  24.  * Improve character tokens, Header, Footer
  25.  * Take care when people don't end lines with HRt
  26.  * Fix major bugs in endnote processing, footnote numbering (and nobody
  27.  *    noticed!)
  28.  * More worries about signed characters.
  29.  * 
  30.  * Revision 1.5  91/07/23  22:59:43  raymond
  31.  * Add COMMENT token, and some bug fixes.
  32.  * 
  33.  * Revision 1.4  91/07/23  22:09:23  raymond
  34.  * Concessions to slightly non-ANSI compilers. (`const', `unsigned char')
  35.  * More patches for machines with signed characters.
  36.  * Fix blatant bug in hex constants.  (Amazed nobody noticed.)
  37.  * New tags SetFn#, Header, Footer.
  38.  * Warning messages for unsupported tokens.
  39.  * Backslahes processed in character tags.
  40.  * Fixed(?) footnotes, endnotes, page length changes.
  41.  * Inserted missing `break's into the huge switch.
  42.  * 
  43.  * Revision 1.3  91/07/12  15:39:44  raymond
  44.  * Spiffy Turbo C support.
  45.  * Some <stdlib.h>'s don't declare errno et al.
  46.  * Command line switches `-s' and `-n' added.
  47.  * More cute warning messages.
  48.  * Dots periodically emitted.
  49.  * Give the enum of token types a name, to placate QuickC.
  50.  * Fix problems with pitch changes and signed characters.
  51.  * 
  52.  * Revision 1.2  91/06/22  08:18:22  raymond
  53.  * <process.h> and fputchar() aren't sufficiently portable.
  54.  * strerror() fails to exist on some so-called ANSI platforms.
  55.  * Removed assumption that characters are unsigned.
  56.  * Forgot to #include <stdarg.h>
  57.  * 
  58.  */
  59.  
  60. /************************************************************************
  61.  * PORTABILITY CONCERNS
  62.  ************************************************************************
  63.  *
  64.  * If possible, compile with unsigned characters.  (Though I think
  65.  * I've taken care of all the places where I assumed characters are
  66.  * unsigned.)
  67.  *
  68.  * This program assumes that your compiler is fully ANSI-conformant.
  69.  * Depending on how non-conformant your compiler is, you may need to
  70.  * set the following symbols at compile time:
  71.  *
  72.  * NO_CONST -- set this if your compiler does not know what `const' means.
  73.  * Cdecl    -- how to tag functions that are variadic.
  74.  *
  75.  * Cdecl is used if you need special declarations for variadic functions.
  76.  * This is used by IBM PC compilers so that you can make the default
  77.  * parameter passing Pascal-style or Fastcalls.
  78.  *
  79.  * Some very machine-dependent stuff happens when trying to open the
  80.  * descriptor file.  Please read dopen.c as well.
  81.  */
  82.  
  83. #ifdef NO_CONST
  84. #define const
  85. #endif
  86.  
  87. #ifndef Cdecl                       /* default is nothing */
  88. #define Cdecl
  89. #endif
  90.  
  91. /************************************************************************
  92.  * This program divides naturally into two parts.
  93.  *
  94.  * The first part reads in the descriptor file and builds the expansions
  95.  * for each of the identifiers listed above.
  96.  * This is the easy part.
  97.  *
  98.  * The second part reads the input file and uses the expansions collected
  99.  * in the first part to transform the file into the output.
  100.  * This is the hard part.
  101.  *
  102.  ************************************************************************/
  103.  
  104. /* And now, the code.
  105.  * We start off with some obvious header files.
  106.  */
  107.  
  108. #include <stdio.h>
  109. #include <stdarg.h>
  110. #include <stdlib.h>
  111. #include <string.h>
  112. #include <ctype.h>
  113.  
  114. /* Some platforms do not define these externals in stdlib.h */
  115. extern int   Cdecl errno;
  116. extern char *Cdecl sys_errlist[];
  117. extern int   Cdecl sys_nerr;
  118.  
  119. /************************************************************************/
  120. /* Some common idioms                                                   */
  121. /************************************************************************/
  122.  
  123. #define do_nothing /* twiddle thumbs */
  124.  
  125. /************************************************************************/
  126. /* Blowing up                                                           */
  127. /************************************************************************/
  128.  
  129. /* The function "error" accepts two arguments.  A FILE pointer and
  130.  * a printf-style argument list.  The printf-style arguments are
  131.  * printed to stderr.  If the FILE is non-NULL, the the remaining
  132.  * contents of the file are printed as well (to provide context), up
  133.  * to 80 characters.
  134.  */
  135.  
  136. void Cdecl error(FILE *fp, char *fmt, ...)
  137. {
  138.   int i;
  139.   va_list ap;
  140.  
  141.   fputs("Error: ", stderr);
  142.   va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap);
  143.   fputc('\n', stderr);
  144.  
  145.   if (fp) {
  146.     fprintf(stderr, "Unread text: ");
  147.     for (i = 0; i < 80 && !feof(fp); i++) fputc(getc(fp), stderr);
  148.     fputc('\n', stderr);
  149.   }
  150.   exit(1);
  151. }
  152.  
  153. /************************************************************************/
  154. /* Command-line switches                                                */
  155. /************************************************************************/
  156. int silent = 0;
  157. int blipinterval = 1024;                /* display blips every 1K */
  158. int blipcount;
  159.  
  160. /************************************************************************/
  161. /* Basic file manipulations                                             */
  162. /************************************************************************/
  163.  
  164. /* We here define a few basic functions.  Let us hope that the first
  165.  * three functions' names are self-descriptive.
  166.  */
  167.  
  168. int next_non_whitespace(FILE *fp)
  169. {
  170.   register int c;
  171.  
  172.   while ((c = getc(fp)) != EOF && isspace(c)) do_nothing;
  173.  
  174.   return c;
  175. }
  176.  
  177. int next_non_space_or_tab(FILE *fp)
  178. {
  179.   register int c;
  180.  
  181.   while ((c = getc(fp)) != EOF && (c == ' ' || c == '\t')) do_nothing;
  182.  
  183.   return c;
  184. }
  185.  
  186. void eat_until_newline(FILE *fp)
  187. {
  188.   register int c;
  189.  
  190.   while ((c = getc(fp)) != EOF && c != '\n') do_nothing;
  191. }
  192.  
  193. /* The function parse_hex grabs a (no-more-than-two-character) hex
  194.  * constant.  Similarly, parse_octal does the same for octal constants.
  195.  */
  196.  
  197. int parse_hex(FILE *fp)
  198. {
  199.   register int c, value;
  200.  
  201.   if (!isxdigit(c = toupper(getc(fp))))
  202.     error(fp, "Expecting a hex digit");
  203.  
  204.   if ((value = c - '0') > 9) value += '0' - 'A' + 10;
  205.  
  206.   if (!isxdigit(c = getc(fp))) { ungetc(c, fp); return value; }
  207.  
  208.   c = toupper(c);
  209.   value = (value << 4) + c - '0';
  210.   if (c > '9') value += '0' - 'A' + 10;
  211.   return value;
  212. }
  213.  
  214. int parse_octal(FILE *fp, register int c)
  215. {
  216.   register int value = c - '0';
  217.  
  218.   if ( (c = getc(fp)) < '0' || c > '7') { ungetc(c, fp); return value; }
  219.  
  220.   value = (value << 3) + c - '0';
  221.  
  222.   if ( (c = getc(fp)) < '0' || c > '7') { ungetc(c, fp); return value; }
  223.  
  224.   return (value << 3) + c - '0';
  225. }
  226.  
  227.  
  228. /************************************************************************/
  229. /* Storing the input strings                                            */
  230. /************************************************************************/
  231.  
  232. /* The input strings are allocated from a large pool we set up at
  233.  * startup.  This lets us do our thing without having to fight
  234.  * with people like malloc and friends.  This method does limit
  235.  * our configuration file to 32K, however.  We hope that this is
  236.  * not a problem.  (It also means that the program can be translated
  237.  * to almost any other language without too much difficulty.)
  238.  *
  239.  * Here's how it works.
  240.  *
  241.  * "pool" is an array of POOL_SIZE characters.  The value of POOL_SIZE
  242.  * is flexible, but shouldn't exceed 65535, since that's the size o